package net.zoneland.knowledge.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import net.zoneland.knowledge.dao.WorkDoneStatusInfoMapper;
import net.zoneland.knowledge.enums.DoneTypeEnum;
import net.zoneland.knowledge.enums.WorkStatusEnum;
import net.zoneland.knowledge.model.LoginUserPojo;
import net.zoneland.knowledge.model.WorkApplyInfo;
import net.zoneland.knowledge.model.WorkDoneInfo;
import net.zoneland.knowledge.model.WorkDoneStatusInfo;
import net.zoneland.knowledge.model.WorkStatusInfo;
import net.zoneland.knowledge.service.WorkDoneStatusInfoService;

/**
 * 已办状态表服务实现.
 * @author bcc
 */
@Service
public class WorkDoneStatusInfoServiceImpl implements WorkDoneStatusInfoService {

    @Autowired
    private WorkDoneStatusInfoMapper workDoneStatusInfoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(final WorkDoneStatusInfo workDoneStatusInfo) {


        final List<WorkStatusInfo> rs = workDoneStatusInfoMapper.queryStatusInfo(workDoneStatusInfo);
        final Date now = DateTime.now().toDate();
        if (CollectionUtils.isEmpty(rs)) {
            workDoneStatusInfo.setId(UUID.randomUUID()
                                         .toString());
            workDoneStatusInfo.setCreateTime(now);
            workDoneStatusInfo.setUpdateTime(now);
            workDoneStatusInfoMapper.insertStatusInfo(workDoneStatusInfo);
            if (StringUtils.isNotBlank(workDoneStatusInfo.getOwnerUid())) {
                workDoneStatusInfoMapper.insertDoneInfo(workDoneStatusInfo);
            }
            return;
        }
        // 更新状态
        workDoneStatusInfoMapper.updateStatusInfo(workDoneStatusInfo);
        // 主工单修改，更新子工单状态时，ownerUid为null 不需要操作已办表
        if (StringUtils.isBlank(workDoneStatusInfo.getOwnerUid())) {
            return;
        }
        final List<WorkDoneInfo> workDoneInfos = workDoneStatusInfoMapper.queryDoneInfo(workDoneStatusInfo);
        if (CollectionUtils.isEmpty(workDoneInfos)) {
            workDoneStatusInfo.setId(UUID.randomUUID().toString());
            workDoneStatusInfoMapper.insertDoneInfo(workDoneStatusInfo);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dealWorkApplyDoneStatus(final WorkApplyInfo info,
                                        final WorkApplyInfo parentWorkApplyInfo,
                                        final List<WorkApplyInfo> subApplys,
                                        final LoginUserPojo user) {
        // 更新当前工单状态
        doDealWorkApplyDoneStatus(info, parentWorkApplyInfo, subApplys, user);
        // 更新父工单状态
        if (null != parentWorkApplyInfo) {
            doDealWorkApplyDoneStatus(parentWorkApplyInfo, null, null, null);
        }
        //更新子工单状态
        Optional.ofNullable(subApplys).ifPresent(subApply -> subApply.stream().forEach(item -> {
            doDealWorkApplyDoneStatus(item, info, null, null);
        }));
    }

    private void doDealWorkApplyDoneStatus(final WorkApplyInfo info,
                                           final WorkApplyInfo parentWorkApplyInfo,
                                           final List<WorkApplyInfo> subApplys,
                                           final LoginUserPojo user) {
        final WorkDoneStatusInfo doneStatusInfo = generateBaseWorkDonStatusInfo(info, user);
        if (WorkStatusEnum.END == info.getStatus()) {
            //已办结的情况,子工单和主工单显示名称不一样
            WorkStatusEnum status = WorkStatusEnum.DISPLAY_FINISH;
            if (null == parentWorkApplyInfo) {
                status = WorkStatusEnum.DISPLAY_COMPLETE;
            }
            doneStatusInfo.setCurrentStatus(status);
            saveOrUpdate(doneStatusInfo);
            return;
        }
        //先判断当前工单是否有待办:
        if (StringUtils.isNotBlank(info.getHandlerUid())) {
            doneStatusInfo.setCurrentHandlerUid(info.getHandlerUid());
            doneStatusInfo.setCurrentHandlerName(info.getHandlerName());
            doneStatusInfo.setCurrentStatus(WorkStatusEnum.DISPLAY_DEAL);
            saveOrUpdate(doneStatusInfo);
            return;

        }
        //判断子工单
        if (null != subApplys) {
            subApplys.stream()
                .filter(item -> WorkSubTaskHandleServiceImpl.CAN_REPORT_STATUS.contains(item.getStatus()))
                .map(item -> {
                    if (StringUtils.isNotBlank(item.getHandlerUid())) {
                        new ImmutablePair<>(item.getHandlerUid(), item.getHandlerName());
                    }
                    //子工单分派后，对上上层工单来说处理人还是中间层工单的分派人
                    return new ImmutablePair<>(item.getAssignUserId(), item.getAssignUserName());
                })
                .reduce((a, b) -> new ImmutablePair<>(a.getLeft() + ";" + b.getLeft(), a.getRight() + ";" + b.getRight()))
                .ifPresent(item -> {
                    doneStatusInfo.setCurrentHandlerUid(item.getLeft());
                    doneStatusInfo.setCurrentHandlerName(item.getRight());
                });
        }
        if (StringUtils.isNotBlank(doneStatusInfo.getCurrentHandlerUid())) {
            doneStatusInfo.setCurrentStatus(WorkStatusEnum.DISPLAY_DEALING);
            saveOrUpdate(doneStatusInfo);
            return;
        }
        if (info.getStatus() == WorkStatusEnum.SUB_CREATOR_CONFIRM && null != parentWorkApplyInfo) {
            // 这个时候待办在上一级
            doneStatusInfo.setCurrentStatus(WorkStatusEnum.DISPLAY_CONFIRM);
            doneStatusInfo.setCurrentHandlerUid(parentWorkApplyInfo.getHandlerUid());
            doneStatusInfo.setCurrentHandlerName(parentWorkApplyInfo.getHandlerName());
        }
        saveOrUpdate(doneStatusInfo);
    }
    @Override
    @Transactional
    public void dealChapterApplyDoneStatus(final WorkApplyInfo info, final LoginUserPojo user) {
        final WorkDoneStatusInfo doneStatusInfo = generateBaseWorkDonStatusInfo(info, user);
        doneStatusInfo.setCurrentStatus(info.getStatus());
        doneStatusInfo.setCurrentHandlerUid(info.getHandlerUid());
        doneStatusInfo.setCurrentHandlerName(info.getHandlerName());
        saveOrUpdate(doneStatusInfo);
    }

    @Override
    public void saveDraftWorkApplyDoneStatus(WorkApplyInfo workApplyInfo, LoginUserPojo user) {
        final WorkDoneStatusInfo workDoneStatusInfo = generateBaseWorkDonStatusInfo(workApplyInfo, user);
        workDoneStatusInfo.setCurrentStatus(WorkStatusEnum.DRAFT);
        workDoneStatusInfo.setCurrentHandlerUid(user.getUserID());
        workDoneStatusInfo.setCurrentHandlerName(user.getUserName());
        final List<WorkStatusInfo> rs = workDoneStatusInfoMapper.queryStatusInfo(workDoneStatusInfo);
        final Date now = DateTime.now().toDate();
        workDoneStatusInfo.setUpdateTime(now);
        if (CollectionUtils.isEmpty(rs)) {
            workDoneStatusInfo.setId(UUID.randomUUID().toString());
            workDoneStatusInfo.setCreateTime(now);
            workDoneStatusInfoMapper.insertStatusInfo(workDoneStatusInfo);
        } else {
            workDoneStatusInfoMapper.updateStatusInfo(workDoneStatusInfo);
        }
    }

    @Override
    public void saveDoneInfo(WorkDoneStatusInfo info) {
        workDoneStatusInfoMapper.insertDoneInfo(info);
    }

    /**
     * 获取基本的已办信息.
     * @param info 工单
     * @param user 当前用户
     * @return
     */
    private  WorkDoneStatusInfo generateBaseWorkDonStatusInfo(final WorkApplyInfo info, final LoginUserPojo user) {
        final WorkDoneStatusInfo doneStatusInfo = new WorkDoneStatusInfo();
        doneStatusInfo.setWorkApplyId(info.getId());
        if (null != user) {
            doneStatusInfo.setOwnerUid(user.getUserID());
            doneStatusInfo.setOwnerName(user.getUserName());
        }
        doneStatusInfo.setDoneType(DoneTypeEnum.DONE_ACTUAL);
        final Date now = DateTime.now().toDate();
        doneStatusInfo.setCreateTime(now);
        doneStatusInfo.setUpdateTime(now);
        return doneStatusInfo;
    }

}
